package cmm.Seman;

import java.util.ArrayList;
import java.util.Objects;

/**
 * Created by Iray on 2017/12/1.
 */
public class Value {

    private int type;

    public double dValue;
    public int iValue ;

    public ArrayList<Integer> ilValue;
    public int ilValueSize ;
    public ArrayList<Double> dlValue;
    public int dlValueSize ;

    public Value(int type) {
        this.type = type;
    }
    public Value(boolean bool) {
        if (bool) {
            this.type = Symbol.TRUE;
        } else {
            this.type = Symbol.FALSE;
        }
    }

    public void setIntArray(int size) {
        ilValue =  new ArrayList<>();
        ilValueSize = size;
        for(int i = 0; i<size;i++)
            ilValue.add(0);
    }

    public void setRealArray(int size) {
        dlValue =  new ArrayList<>();
        dlValueSize = size;
        for(int i = 0; i<size;i++)
            dlValue.add(0.0);
    }

    public int getType() {
        return type;
    }

    public void setType(int type) {
        this.type = type;
    }


    // pay attention
    public double getdValue() {
        return dlValue.get(0);
    }

    // pay attention
    public void setdValue(double dValue) {
        dlValue =  new ArrayList<>();
        dlValue.add(dValue);
        dlValueSize = 1;
    }

    // pay attention
    public int getiValue() {
        return ilValue.get(0);
    }

    // pay attention
    public void setiValue(int iValue) {
        ilValue =  new ArrayList<>();
        ilValue.add(iValue);
        ilValueSize = 1;

    }

    public ArrayList<Integer> getIlValue() {
        return ilValue;
    }

    public void setIlValue(ArrayList<Integer> ilValue) {
        this.ilValue = ilValue;
    }

    public ArrayList<Double> getDlValue() {
        return dlValue;
    }

    public void setDlValue(ArrayList<Double> dlValue) {
        this.dlValue = dlValue;
    }

    public int getIlValueSize() {
        return ilValueSize;
    }

    public int getDlValueSize() {
        return dlValueSize;
    }


    public String toString(int idx) throws Exception {

//        if(dValue != Double.NaN)
//            return String.valueOf(dlValue);
//        if(iValue != Integer.MIN_VALUE)
//            return String.valueOf(iValue);

        if(ilValueSize > 0) {
            if(ilValueSize <= idx || idx < 0)
                throw new Exception(type + " 数组跃越界");
            return String.valueOf(ilValue.get(idx));
        }

        if(dlValueSize > 0) {
            if(dlValueSize <= idx || idx < 0)
                throw new Exception(type + " 数组跃越界");
            return String.valueOf(dlValue.get(idx));
        }

        return "";
    }

    public void setIlValue(int idx, int value) {
        ilValue.set(idx, value);
    }

    public void setDlValue(int idx, double value) {
        dlValue.set(idx, value);
    }




    public Value ADD(Value value) throws Exception {
        if(type == Symbol.INT) {
            if(value.getType() == Symbol.INT) {
                Value v = new Value(Symbol.INT);
                v.setiValue(ilValue.get(0) + value.getiValue());
                return v;
            } else if (value.getType() == Symbol.REAL) {
                Value v = new Value(Symbol.REAL);
                v.setdValue(dlValue.get(0) + value.getdValue());
                return v;
            }
        }else if(type == Symbol.REAL){
            Value v = new Value(Symbol.REAL);
            if(value.getType() == Symbol.INT) {
                v.setdValue(ilValue.get(0) + value.getiValue());
                return v;
            } else if (value.getType() == Symbol.REAL) {
                v.setdValue(dlValue.get(0) + value.getdValue());
                return v;
            }
        }
        throw new Exception("add wrong");

    }
    public Value SUB(Value value) throws Exception {
        if(type == Symbol.INT) {
            if(value.getType() == Symbol.INT) {
                Value v = new Value(Symbol.INT);
                v.setiValue(ilValue.get(0) - value.getiValue());
                return v;
            } else if (value.getType() == Symbol.REAL) {
                Value v = new Value(Symbol.REAL);
                v.setdValue(ilValue.get(0) - value.getdValue());
                return v;
            }
        }else if(type == Symbol.REAL){
            Value v = new Value(Symbol.REAL);
            if(value.getType() == Symbol.INT) {
                v.setdValue(dlValue.get(0) - value.getiValue());
                return v;
            } else if (value.getType() == Symbol.REAL) {
                v.setdValue(dlValue.get(0) - value.getdValue());
                return v;
            }
        }
        throw new Exception("sub wrong");
    }
    public Value MUL(Value value) throws Exception {
        if(type == Symbol.INT) {
            if(value.getType() == Symbol.INT) {
                Value v = new Value(Symbol.INT);
                v.setiValue(ilValue.get(0) * value.getiValue());
                return v;
            } else if (value.getType() == Symbol.REAL) {
                Value v = new Value(Symbol.REAL);
                v.setdValue(ilValue.get(0) * value.getdValue());
                return v;
            }
        }else if(type == Symbol.REAL){
            Value v = new Value(Symbol.REAL);
            if(value.getType() == Symbol.INT) {
                v.setdValue(dlValue.get(0) * value.getiValue());
                return v;
            } else if (value.getType() == Symbol.REAL) {
                v.setdValue(dlValue.get(0) * value.getdValue());
                return v;
            }
        }
        throw new Exception("mul wrong");
    }
    public Value DIV(Value value) throws Exception {

        if(value.dlValueSize >0 && value.getdValue() == 0.0)
            throw new Exception("divider can not be 0");

        if(value.ilValueSize >0 && value.getiValue() == 0)
            throw new Exception("divider can not be 0");

        if(type == Symbol.INT) {
            if(value.getType() == Symbol.INT) {
                Value v = new Value(Symbol.INT);
                v.setiValue(ilValue.get(0) / value.getiValue());
                return v;
            } else if (value.getType() == Symbol.REAL) {
                Value v = new Value(Symbol.REAL);
                v.setdValue(ilValue.get(0) / value.getdValue());
                return v;
            }
        }else if(type == Symbol.REAL){
            Value v = new Value(Symbol.REAL);
            if(value.getType() == Symbol.INT) {
                v.setdValue(dlValue.get(0) / value.getiValue());
                return v;
            } else if (value.getType() == Symbol.REAL) {
                v.setdValue(dlValue.get(0) / value.getdValue());
                return v;
            }
        }
        throw new Exception("div wrong");
    }

    public Value GT(Value value) throws Exception {
        if (this.type == Symbol.INT) {
            if (value.type == Symbol.INT) {
                return new Value(this.ilValue.get(0) > value.ilValue.get(0));
            } else if (value.type == Symbol.REAL) {
                return new Value(this.ilValue.get(0) > value.dlValue.get(0));
            }
        } else if (this.type == Symbol.REAL) {
            if (value.type == Symbol.INT) {
                return new Value(this.dlValue.get(0) > value.ilValue.get(0));
            } else if (value.type == Symbol.REAL) {
                return new Value(this.dlValue.get(0) > value.dlValue.get(0));
            }
        }
        throw new Exception("逻辑比较非法");
    }

    public Value EQ(Value value) throws Exception {
        if (this.type == Symbol.INT) {
            if (value.type == Symbol.INT) {
                return new Value(Objects.equals(this.ilValue.get(0), value.ilValue.get(0)));
            } else if (value.type == Symbol.REAL) {
                return new Value(Objects.equals(this.ilValue.get(0), value.dlValue.get(0)));
            }
        } else if (this.type == Symbol.REAL) {
            if (value.type == Symbol.INT) {
                return new Value(Objects.equals(this.dlValue.get(0), value.ilValue.get(0)));
            } else if (value.type == Symbol.REAL) {
                return new Value(Objects.equals(this.dlValue.get(0), value.dlValue.get(0)));
            }
        }
        throw new Exception("逻辑比较非法");
    }

    public Value OR(Value value) {
        if (this.type == Symbol.TRUE || value.type == Symbol.TRUE) {
            return new Value(Symbol.TRUE);
        } else {
            return new Value(Symbol.FALSE);
        }
    }
    public Value GET(Value value) throws Exception {
        return this.GT(value).OR(this.EQ(value));
    }
    public Value LT(Value value) throws Exception {
        return NOT(this.GET(value));
    }
    public Value LET(Value value) throws Exception {
        return NOT(this.GT(value));
    }
    public Value NEQ(Value value) throws Exception {
        return NOT(this.EQ(value));
    }

    public static Value NOT(Value value) throws Exception {
        if (value.type == Symbol.TRUE) {
            return new Value(Symbol.FALSE);
        } else if (value.type == Symbol.FALSE) {
            return new Value(Symbol.TRUE);
        } else if (value.type == Symbol.INT) {
            Value rv = new Value(Symbol.INT);
            rv.setiValue(value.ilValue.get(0) * -1);
            return rv;
        } else if (value.type == Symbol.REAL) {
            Value rv = new Value(Symbol.REAL);
            rv.setdValue(value.dlValue.get(0) * -1);
            return rv;
        }
        throw new Exception("负号使用非法");
    }


}
